package com.qlhx.filter;

import java.nio.CharBuffer;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.atomic.AtomicReference;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.NettyDataBufferFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.filter.reactive.HiddenHttpMethodFilter;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;

import com.qlhx.service.BaseClientService;

import io.netty.buffer.ByteBufAllocator;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

public class TokenFilter implements GlobalFilter, Ordered {
	
	@Autowired
	BaseClientService baseClientService;
	
	private static final String ALL = "*";
    private static final String MAX_AGE = "18000L";
    
	private  final Logger logger = LoggerFactory.getLogger(TokenFilter.class);
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//    	 ServerHttpRequest request = exchange.getRequest();
//    	 ServerHttpResponse response = exchange.getResponse();
//         HttpHeaders headers = response.getHeaders();
//         headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
//         headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "POST, GET, PUT, OPTIONS, DELETE, PATCH");
//         headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
//         headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, ALL);
//         headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, ALL);
//         headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, MAX_AGE);
//         if (request.getMethod() == HttpMethod.OPTIONS) {
//             response.setStatusCode(HttpStatus.OK);
//             return Mono.empty();
//         }
         return chain.filter(exchange);
    
    	
    	
//    	ServerHttpRequest request = exchange.getRequest();
//    	ServerHttpResponse originalResponse = exchange.getResponse();
//    	String requestPath = request.getPath().value();
//    	if(requestPath.endsWith("user/login"))
//    	{
//    		return chain.filter(exchange);
//    	}
//    	String token = request.getHeaders().getFirst("token");
//    	ApiResult<String>  result = new ApiResult<String>();
//    	if(token == null)
//    	{
//    		result.setCode(ApiResult.NO_LOGIN);
//    		result.setMsg("未登录");
//    		logger.info("=======token为空======");
//    	}
//    	else
//    	{
//    		ApiResult<String> ar = baseClientService.islogin(token);
//    		if(ar.getCode().intValue() != ApiResult.SUCCESS )
//    		{
//    			result.setCode(ApiResult.NO_LOGIN);
//        		result.setMsg("未登录");
//        		logger.info("=======token:"+token+" 验证失败======");
//    		}
//    		else
//    		{
//    			logger.info("=======token:"+token+" 验证成功，用户为:"+ar.getContent()+"======");
//    			return chain.filter(exchange);
//    		}
//    	}
//        originalResponse.setStatusCode(HttpStatus.OK);
//        originalResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
//        byte[] response = JSON.toJSONString(result).getBytes(StandardCharsets.UTF_8);
//        DataBuffer buffer = originalResponse.bufferFactory().wrap(response);
//        return originalResponse.writeWith(Flux.just(buffer));
    }
    
    @Bean
    public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
        return new HiddenHttpMethodFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
                return chain.filter(exchange);
            }
        };
    }
 
 
    @Bean
    public WebFilter corsFilter() {
        return (ServerWebExchange ctx, WebFilterChain chain) -> {
            ServerHttpRequest request = ctx.getRequest();
            if (!CorsUtils.isCorsRequest(request)) {
                return chain.filter(ctx);
            }
 
            HttpHeaders requestHeaders = request.getHeaders();
            ServerHttpResponse response = ctx.getResponse();
            HttpMethod requestMethod = requestHeaders.getAccessControlRequestMethod();
            HttpHeaders headers = response.getHeaders();
            headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, requestHeaders.getOrigin());
            headers.addAll(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, requestHeaders.getAccessControlRequestHeaders());
            if (requestMethod != null) {
                headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, requestMethod.name());
            }
            headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
//            headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, ALL);
//            headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, MAX_AGE);
            if (request.getMethod() == HttpMethod.OPTIONS) {
                response.setStatusCode(HttpStatus.OK);
                return Mono.empty();
            }
            return chain.filter(ctx);
        };
    }

    
    
    private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) {
        //获取请求体
        Flux<DataBuffer> body = serverHttpRequest.getBody();
 
        AtomicReference<String> bodyRef = new AtomicReference<>();
        body.subscribe(buffer -> {
            CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());
            DataBufferUtils.release(buffer);
            bodyRef.set(charBuffer.toString());
        });
        //获取request body
        return bodyRef.get();
    }
 
    private DataBuffer stringBuffer(String value) {
        byte[] bytes = value.getBytes(StandardCharsets.UTF_8);
 
        NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);
        DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length);
        buffer.write(bytes);
        return buffer;
    }

    @Override
    public int getOrder() {
        return -100;
    }
}

